﻿using System;
using System.Linq;
using System.Windows.Input;
using RIA.ServicesLibrary.Web.Services;
using System.ServiceModel.DomainServices.Client;
using RIA.ServicesLibrary.Web.Models;

namespace RIA.ViewModel
{
    public class CustomerDetailsViewModel : ViewModelBase
    {
        #region Member Variables
        private CustomerContext _customerContext = new CustomerContext ();
        private Customer _customer;
        private ICommand _loadCommand;
        #endregion


        
        public CustomerDetailsViewModel ()
        {
            //_customerContext.Customers.Add ( _customer );
        }
        

        #region Customer

        public Customer Customer
        {
            get { return _customer; }
            set
            {  
                _customer = value;
                OnPropertyChanged ( "Customer" );
            }
        }

        #endregion //Properties

        #region LoadCommand 

        public ICommand LoadCommand
        {
        get
        {
            if ( _loadCommand == null )
            {
                _loadCommand = new DelegateCommand ( LoadCustomer, ( o ) => true );

           }
            return _loadCommand;
        }
        }

        public void LoadCustomer ( object param )
        {
            int customerid = (int)param;
            ShowBusyStatus ();
            EntityQuery<Customer> qry = _customerContext.GetCustomersQuery ();
            qry = qry.Where<Customer> ( c => c.CustomerID == customerid );
            LoadOperation<Customer> op = _customerContext.Load ( qry, true );
            op.Completed += ( x, y ) =>
            {
                HideBusyStatus ();
                if ( op.HasError )
                {
                    System.Windows.MessageBox.Show ( op.Error.ToString (), "Load Error",System.Windows.MessageBoxButton.OK );
                    op.MarkErrorAsHandled ();
                }
                else
                {
                    if ( op.Entities.Count () != 0 )
                    {
                        this.Customer = op.Entities.First ();
                    }
                }

            };
        }
        #endregion

        #region UpdateCommand 

     

        ICommand _updateCommand;


        public ICommand UpdateCommand
        {
            get
            {
                if ( _updateCommand == null )
                {
                    _updateCommand = new DelegateCommand( UpdateExecute, CanUpdateExecute );
                }
                return _updateCommand;
            }
        }

        

        #region Update Command Methods

        bool CanUpdateExecute ( object param )
        {
            if ( this._customer != null )
            {
                bool haschanges = _customerContext.HasChanges;
                bool hasValidationErrors = this._customer.HasValidationErrors;
                return haschanges && !hasValidationErrors;
            }
            else
            {
                return false;
            }
            
            
        }

        void UpdateExecute ( object param )
        {
            if ( _customer != null )
            {
                this.ShowBusyStatus ();
                var op =_customerContext.SubmitChanges ();
                op.Completed += new EventHandler ( SaveCustomer_Completed );
            }
        }
        private void SaveCustomer_Completed ( object sender, EventArgs e )
        {
            this.HideBusyStatus ();
            SubmitOperation op = sender as SubmitOperation;
            
            if ( !op.HasError )
            {
                // You may wish to notify the View that the save is complete
                // by raising an event here, and responding to it in the View
                RaiseOnSavedData ();
                Customer _currentCustomer = this._customer;
                this.Customer = null;
                this.Customer = _currentCustomer;
                
            }
            else
            {
 
                    DomainOperationException error = op.Error as DomainOperationException;
                    switch ( error.Status )
                    {
                        case OperationErrorStatus.Conflicts:
                            // Handle concurrency violations
                            // Loop through the entities with concurrency violations
                                foreach (Customer customer in op.EntitiesInError)
                                {
                                    EntityConflict conflictinfo = customer.EntityConflict;
                                    Customer currentProduct = conflictinfo.CurrentEntity as Customer;
                                    Customer originalProduct = conflictinfo.OriginalEntity as Customer;
                                    Customer storeProduct = conflictinfo.StoreEntity as Customer;

                                // Handle any conflicts automatically (if you wish)
                                // You can get the names of the properties whose value has changed
                                // from the conflictinfo.PropertyNames property
                                // Force this user's version to overwrite the version on the server
                                    customer.EntityConflict.Resolve ();
                                // resubmit changes to server
                                    _customerContext.SubmitChanges ();
                                }
                            break;
                        case OperationErrorStatus.ServerError:
                            // Handle server errors
                            break;
                        case OperationErrorStatus.Unauthorized:
                            // Handle unauthorized domain operation access
                            break;
                        case OperationErrorStatus.ValidationFailed:
                            // Handle validation rule failures
                            break;
                        default:
                           
                            break;
                   }
                   System.Windows.MessageBox.Show ( op.Error.ToString (), "update Error", System.Windows.MessageBoxButton.OK );
                   op.MarkErrorAsHandled ();
                
            }
        }

        #endregion //Command Methods

        #endregion

        #region LoadCustomerDetailsCommand
        ICommand _loadCustomerDetails;
        public ICommand LoadCustomerDetails
        {
            get
            {
                if ( _loadCustomerDetails == null )
                {
                    _loadCustomerDetails = new DelegateCommand( param => LoadCustomerDetailsExecute ( param )
                        , param => CanLoadCustomerDetailsExecute ( param ) );
                }
                return _loadCustomerDetails;
            }
        }
        bool CanLoadCustomerDetailsExecute ( object param )
        {
            return true;
        }

        public void LoadCustomerDetailsExecute ( object param )
        {
            int customerid = ( int ) param;
            ShowBusyStatus ();
            EntityQuery<Customer> qry = _customerContext.GetCustomerQuery (customerid);

            LoadOperation<Customer> op = _customerContext.Load ( qry, true );
            op.Completed += ( x, y ) =>
            {
                HideBusyStatus ();
                if ( op.HasError )
                {
                    System.Windows.MessageBox.Show ( op.Error.ToString (), "Load  customer details Error", System.Windows.MessageBoxButton.OK );
                    op.MarkErrorAsHandled ();
                }
                else
                {
                    if ( op.Entities.Count () != 0 )
                    {
                        this.Customer = null;
                        this.Customer = op.Entities.First ();
                    }
                    RaiseLoadedData ();
                }

            };
        }

       

        #endregion //Command Properties

        public void DeleteAddress (CustomerAddress ca)
        {
            _customerContext.CustomerAddresses.Remove ( ca );
            _customerContext.Addresses.Remove ( ca.Address );
        }

        public void InsertAddress ( CustomerAddress ca )
        {
            _customer.CustomerAddresses.Add ( ca );
        }
        public void AddCustomer ( Customer newObj )
        {
            _customerContext.Customers.Add ( newObj );
        }

        public CustomerAddress CreateNewCompanyAddress ()
        {
            var obj = new CustomerAddress ()
            {
                CustomerID = this.Customer.CustomerID,
                ModifiedDate = DateTime.Now,
                rowguid = Guid.NewGuid (),
                AddressType = "Main Office",
                Customer = this.Customer,
                Address = new Address ()
                {
                    ModifiedDate = DateTime.Now,
                    rowguid = Guid.NewGuid (),
                    AddressLine1 = string.Empty
                }
            };
            return obj;
        }

        public Customer CreateCustomer ()
        {
            Customer c = new Customer ();
            c.rowguid = Guid.NewGuid ();
            c.ModifiedDate = DateTime.Now;
            c.PasswordHash = "L/Rlwxzp4w7RWmEgXX+/A7cXaePEPcp+KwQhl2fJL7w=";
            c.PasswordSalt = "1KjXYs4=";
            return c;
        }

        
    }

}
